﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using Restful.Net.Reflection;

namespace Restful.Net.Tests
{
    [TestFixture]
    public class TypeMapTest
    {
        // TODO: Write more unit tests
        [Test]
        public void ShouldReturnGetAllTestMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn}");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Get);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("GetAllTest"));
        }

        [Test]
        public void ShouldReturnGetTestMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn/123");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Get);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("GetTest"));
        }

        [Test]
        public void ShouldReturnDeleteTestMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn/123");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Delete);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("DeleteTest"));
        }

        [Test]
        public void ShouldReturnCreateTestMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Post);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("CreateTest"));
        }

        [Test]
        public void ShouldReturnUpdateTestMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn/123");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Put);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("UpdateTest"));
        }

        [Test]
        public void ShouldReturnPatchTestMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn/123");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Patch);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("PatchTest"));
        }

        [Test]
        public void ShouldReturnBeginDeleteAllMethod()
        {
            ServiceTypeMap map = new ServiceTypeMap(typeof(TestService), "test/{ownerid}");
            Uri baseUri = new Uri("http://localhost/");

            Uri testUri = new Uri("http://localhost/test/bjorn");

            MethodMatch methodMatch = map.GetMethod(baseUri, testUri, HttpVerb.Delete);
            Assert.That(methodMatch, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.IsAsync, Is.True);
            Assert.That(methodMatch.RestMethod.Method.Name, Is.EqualTo("BeginDeleteAll"));
            Assert.That(methodMatch.RestMethod.EndMethod, Is.Not.Null);
            Assert.That(methodMatch.RestMethod.EndMethod.Name, Is.EqualTo("EndDeleteAll"));
        }
    }

    public class TestService
    {

        [RestMethod(UriTemplate = "/{itemID}", Verb = HttpVerb.Delete)]
        public void DeleteTest(string itemID)
        {
        }

        [RestMethod(UriTemplate = "", Verb = HttpVerb.Post)]
        public void CreateTest(Test item)
        {
        }

        [RestMethod(UriTemplate = "/{itemID}", Verb = HttpVerb.Put)]
        public void UpdateTest(Test item)
        {

        }

        [RestMethod(UriTemplate = "/{itemID}", Verb = HttpVerb.Patch)]
        public void PatchTest(Test item)
        {

        }
        [RestMethod(UriTemplate = "", Verb = HttpVerb.Get)]
        public List<Test> GetAllTest()
        {
            return null;
        }
        
        [RestMethod(UriTemplate = "/{itemID}", Verb = HttpVerb.Get)]
        public Test GetTest(string itemID)
        {
            return null;
        }

        [RestMethod(UriTemplate = "", Verb = HttpVerb.Delete)]
        public IAsyncResult BeginDeleteAll(AsyncCallback callback, object state)
        {
            return null;
        }

        public void EndDeleteAll(IAsyncResult result)
        {

        }

        public class Test
        {
            public string ItemID
            {
                get;
                set;
            }

            public string Name
            {
                get;
                set;
            }
        }
    }
}
